package com.my.lucky.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.TextStyle;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.stream.Stream;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashSet;
import java.util.Set;


public class DateUtils {


//    /**
//     * 获取今天前推指定天数的日期时间（跳过周末）
//     * @param days 要前推的天数（工作日）
//     * @return 计算后的日期时间
//     */
//    public static LocalDateTime minusDaysExcludeWeekendAndYesterday(LocalDateTime now, int days) {
//        LocalDate today = now.toLocalDate();
//        LocalDate targetDate = today.minusDays(days);
//        // 计算目标日期到今天之间的周末天数
//        long weekendDays = countWeekendDaysBetween(targetDate, today);
////        System.out.println("周末天数=="+weekendDays);
//        // 如果有周末，则再延后相应天数
//        if (weekendDays > 0) {
//            targetDate = targetDate.minusDays(weekendDays);
//        }
//        // 如果目标日期是周六或周日，调整为上周五
//        if (targetDate.getDayOfWeek() == DayOfWeek.SATURDAY) {
//            targetDate = targetDate.minusDays(1); // 周六 -> 周五
//        } else if (targetDate.getDayOfWeek() == DayOfWeek.SUNDAY) {
//            targetDate = targetDate.minusDays(2); // 周日 -> 周五
//        }
//        return LocalDateTime.of(targetDate, LocalTime.MIDNIGHT);
//    }

    /**
     * 获取今天前推指定天数的日期时间（跳过周末）
     * @param now 基准时间
     * @param days 要前推的工作日天数
     * @return 计算后的日期时间（午夜）
     */
    public static LocalDateTime minusDaysExcludeWeekendAndYesterday(LocalDateTime now, int days) {
        // 边界处理：如果天数小于等于0，返回今天午夜
        if (days <= 0) {
            return LocalDateTime.of(now.toLocalDate(), LocalTime.MIDNIGHT);
        }

        LocalDate currentDate = now.toLocalDate();
        int remainingDays = days;

        // 逐天向前推算，只计数工作日
        while (remainingDays > 0) {
            currentDate = currentDate.minusDays(1); // 向前推一天

            // 检查当前日期是否为工作日（非周六和周日）
            DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
            if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY
                    &&!get2025Holidays().contains(currentDate)
            ) {
                remainingDays--; // 是工作日，减少剩余计数
            }
        }

        // 返回目标日期的午夜时间
        return LocalDateTime.of(currentDate, LocalTime.MIDNIGHT);
    }


    /**
     * 计算指定日期减去指定工作日（排除周末和2025年法定节假日）后的日期
     * @param now 基准日期时间
     * @param days 需要减去的工作日天数
     * @return 计算后的日期（午夜时间）
     */
    public static LocalDateTime minusDaysExcludeWeekendAnd2025Holidays(LocalDateTime now, int days) {
        // 获取2025年法定节假日集合
        Set<LocalDate> holidays2025 = get2025Holidays();
        // 获取2025年调休工作日集合
        Set<LocalDate> adjustedWorkdays2025 = get2025AdjustedWorkdays();

        return minusDaysExcludeWeekendAndYesterday(now, days);
    }

    /**
     * 获取2025年法定节假日（推测）
     */
    private static Set<LocalDate> get2025Holidays() {
        Set<LocalDate> holidays = new HashSet<>();

        // 元旦
        holidays.add(LocalDate.of(2025, 1, 1));
        holidays.add(LocalDate.of(2025, 1, 2));
        holidays.add(LocalDate.of(2025, 1, 3));

        // 春节
        holidays.add(LocalDate.of(2025, 1, 29));
        holidays.add(LocalDate.of(2025, 1, 30));
        holidays.add(LocalDate.of(2025, 1, 31));
        holidays.add(LocalDate.of(2025, 2, 1));
        holidays.add(LocalDate.of(2025, 2, 2));
        holidays.add(LocalDate.of(2025, 2, 3));
        holidays.add(LocalDate.of(2025, 2, 4));

        // 清明节
        holidays.add(LocalDate.of(2025, 4, 4));
        holidays.add(LocalDate.of(2025, 4, 5));
        holidays.add(LocalDate.of(2025, 4, 6));

        // 劳动节
        holidays.add(LocalDate.of(2025, 5, 1));
        holidays.add(LocalDate.of(2025, 5, 2));
        holidays.add(LocalDate.of(2025, 5, 3));
        holidays.add(LocalDate.of(2025, 5, 4));
        holidays.add(LocalDate.of(2025, 5, 5));

        // 端午节
        holidays.add(LocalDate.of(2025, 5, 30));
        holidays.add(LocalDate.of(2025, 5, 31));
        holidays.add(LocalDate.of(2025, 6, 1));

        // 中秋节
        holidays.add(LocalDate.of(2025, 9, 12));
        holidays.add(LocalDate.of(2025, 9, 13));
        holidays.add(LocalDate.of(2025, 9, 14));

        // 国庆节
        holidays.add(LocalDate.of(2025, 10, 1));
        holidays.add(LocalDate.of(2025, 10, 2));
        holidays.add(LocalDate.of(2025, 10, 3));
        holidays.add(LocalDate.of(2025, 10, 4));
        holidays.add(LocalDate.of(2025, 10, 5));
        holidays.add(LocalDate.of(2025, 10, 6));
        holidays.add(LocalDate.of(2025, 10, 7));
        holidays.add(LocalDate.of(2025, 10, 8));

        return holidays;
    }

    /**
     * 获取2025年调休工作日（推测）
     */
    private static Set<LocalDate> get2025AdjustedWorkdays() {
        Set<LocalDate> adjustedWorkdays = new HashSet<>();

        // 春节调休
        adjustedWorkdays.add(LocalDate.of(2025, 1, 25)); // 周六
        adjustedWorkdays.add(LocalDate.of(2025, 2, 8));  // 周六

        // 清明节调休
        adjustedWorkdays.add(LocalDate.of(2025, 4, 7));  // 周日

        // 劳动节调休
        adjustedWorkdays.add(LocalDate.of(2025, 4, 27)); // 周日
        adjustedWorkdays.add(LocalDate.of(2025, 5, 10)); // 周六

        // 端午节调休
        adjustedWorkdays.add(LocalDate.of(2025, 5, 25)); // 周六

        // 中秋节调休
        adjustedWorkdays.add(LocalDate.of(2025, 9, 11)); // 周四（假设调休）

        // 国庆节调休
        adjustedWorkdays.add(LocalDate.of(2025, 9, 28)); //
        adjustedWorkdays.add(LocalDate.of(2025, 10, 11)); //

        return adjustedWorkdays;
    }


    /**
     * 计算两个日期之间的周末天数
     *
     * @param start 开始日期（包含）
     * @param end   结束日期（不包含）
     * @return 周末天数
     */
    private static long countWeekendDaysBetween(LocalDate start, LocalDate end) {
        return Stream.iterate(start, date -> date.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end))
                .filter(date -> date.getDayOfWeek() == DayOfWeek.SATURDAY ||
                        date.getDayOfWeek() == DayOfWeek.SUNDAY)
                .count();
    }

    // 默认时区：亚洲/上海
    private static final ZoneId DEFAULT_ZONE = ZoneId.of("Asia/Shanghai");

    /**
     * 获取指定日期的星期几（中文全称）
     */
    public static String getChineseWeekday(LocalDate date) {
        if (date == null) {
            return "";
        }
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINESE);
    }

    public static void main(String[] args) {

        // 计算从现在起减去5个工作日（排除周末和2025年法定节假日）的日期
        LocalDateTime result = minusDaysExcludeWeekendAnd2025Holidays(
                LocalDateTime.now(),
                1
        );

        System.out.println("计算结果：" + result);


        // 1. 获取当前日期
        LocalDate date = LocalDate.now();

        // 2. 也可以指定特定日期（年, 月, 日）
        // LocalDate date = LocalDate.of(2023, 10, 1); // 2023年10月1日

        // 3. 获取星期几（返回DayOfWeek枚举）
        DayOfWeek dayOfWeek = date.getDayOfWeek();

        // 4. 几种常用的输出方式
        // 4.1 数字表示（1=周一，7=周日，国际标准）
        int weekNumber = dayOfWeek.getValue();
        System.out.println("数字表示: " + weekNumber);

        // 4.2 英文名称（如MONDAY, TUESDAY）
        String englishName = dayOfWeek.name();
        System.out.println("英文名称: " + englishName);

        // 4.3 中文名称（需要指定Locale）
        String chineseName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINESE);
        System.out.println("中文名称: " + chineseName);


        // 正常测试
        // 创建示例LocalDateTime对象 (对应 2025-09-29T18:44:22)
        LocalDateTime dateTime = LocalDateTime.of(2025, 9, 29, 18, 44, 22);

        // 格式化展示
        System.out.println("原始格式: " + format(dateTime, FORMATTER_ISO)); // 2025-09-29T18:44:22
        System.out.println("年月日 时分秒: " + toYmdHms(dateTime)); // 2025-09-29 18:44:22
        System.out.println("月日 时分: " + toMdHm(dateTime)); // 09-29 18:44
        System.out.println("年月日: " + format(dateTime, FORMATTER_YMD)); // 2025-09-29
        System.out.println("时分秒: " + format(dateTime, FORMATTER_HMS)); // 18:44:22

        // 处理null的情况
        System.out.println("处理null: " + toYmdHms(null)); // null
    }

    // 定义常用的日期时间格式器
    public static final DateTimeFormatter FORMATTER_ISO = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
    public static final DateTimeFormatter FORMATTER_YMD_HMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter FORMATTER_YMD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter FORMATTER_MD_HM = DateTimeFormatter.ofPattern("MM-dd HH:mm");
    public static final DateTimeFormatter FORMATTER_HMS = DateTimeFormatter.ofPattern("HH:mm:ss");

    /**
     * 将LocalDateTime格式化为指定格式的字符串
     * @param dateTime 要格式化的LocalDateTime对象
     * @param formatter 格式化器
     * @return 格式化后的字符串，若输入为null则返回null
     */
    public static String format(LocalDateTime dateTime, DateTimeFormatter formatter) {
        if (dateTime == null || formatter == null) {
            return null;
        }
        try {
            return dateTime.format(formatter);
        } catch (DateTimeParseException e) {
            System.err.println("LocalDateTime格式化失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 格式化示例：转换为 "yyyy-MM-dd HH:mm:ss" 格式
     */
    public static String toYmdHms(LocalDateTime dateTime) {
        return format(dateTime, FORMATTER_YMD_HMS);
    }

    /**
     * 格式化示例：转换为 "MM-dd HH:mm" 格式
     */
    public static String toMdHm(LocalDateTime dateTime) {
        return format(dateTime, FORMATTER_MD_HM);
    }



}
